'use strict';

const Core = require('@alicloud/pop-core');
const ipfsAPI = require('ipfs-http-client');
const BigNumber = require('bignumber.js').BigNumber;
const PDFDocument = require('pdfkit');
const Path = require('path');
const fs = require('fs');
const moment = require('moment');
const got = require('got');
const crypto = require('crypto');
const chainsql = require('./chainsql');
const Joi = require('joi');
const _ = require('lodash');
const config = require('../configs');
// const ipfs = ipfsAPI(config.ipfs.url);
// const smsClient = new Core({
//   accessKeyId: config.sms.accessKeyId,
//   accessKeySecret: config.sms.secretAccessKey,
//   endpoint: config.sms.endpoint,
//   apiVersion: config.sms.apiVersion
// });

/**
 * sha256 签名算法
 * @param {String} finalStr - 需要签名的字符串
 */
const sha256 = (str, salt) => {
  if (!salt) {
    salt = 'peersafe';
  }
  let hash = crypto
    .createHmac('sha256', salt)
    .update(str, 'utf8')
    .digest('hex');
  return hash;
};
const schema = Joi.object({
  limit: Joi.number().min(1).max(1000),
  offset: Joi.number().min(0),
  pwd: Joi.string().regex(/^[A-Fa-f0-9]{32}$/),
  phone: Joi.string().regex(/^[1]([3-9])[0-9]{9}$/),
  email: Joi.string().email(),
  hash: Joi.string().regex(/^[A-Fa-f0-9]{64}$/),
  openid: Joi.string().min(25).max(40),
  nickName: Joi.string().min(1).max(15),
  location: Joi.string().min(2).max(100),
  dataType: Joi.number().min(1).max(5),
  url: Joi.string().regex(
    /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/
  ),
  inviteesCode: Joi.string().regex(/^[A-Za-z0-9]{6}$/)
});

/**
 * 生成验证码
 * @return {String} 验证码
 */
function createSMSCode() {
  let code = '';
  const codeLength = 6;
  const selectChar = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  for (let i = 0; i < codeLength; i++) {
    const charIndex = Math.floor(Math.random() * 10);

    code += selectChar[charIndex];
  }
  return code;
}

/**
 * 获取请求对应ip
 * @param {Object} req 请求头内容
 * @return {String} ip地址
 */
function getClientIp(req) {
  return (
    req.headers['x-forwarded-for'] || // 判断是否有反向代理 IP
    req.connection.remoteAddress || // 判断 connection 的远程 IP
    req.socket.remoteAddress || // 判断后端的 socket 的 IP
    req.connection.socket.remoteAddress
  );
}
/**
 * 发送验证码
 * @param {String} str 发送内容
 * @return {String} 发送内容
 */
async function sendSMS(phone) {
  var codeStr = createSMSCode();
  const codeJson = JSON.stringify({
    code: codeStr
  });
  const params = {
    PhoneNumbers: phone,
    SignName: config.sms.signName,
    TemplateCode: config.sms.templateCode.loginOrRegister,
    TemplateParam: codeJson,
    RegionId: 'cn-shanghai'
  };
  const requestOption = {
    method: 'POST'
  };
  const result = await smsClient.request('SendSms', params, requestOption);
  if (result.Code == 'OK') {
    return codeStr;
  } else {
    throw new Error(result.Code);
  }
}

//上传文件到ipfs
async function uploadFile(path) {
  const stream = fs.createReadStream(path);
  var res = await ipfs.add(stream);
  return res.path;
}

//下载文件
async function downloadFile(filePath) {
  return await got.stream.post(`${config.ipfs.url}/cat/${filePath}`);
}

//10进制转52
function string10to52(str) {
  var chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ';
  var radix = chars.length;
  var arr = [];
  var qutient = BigNumber(str);
  while (qutient > 0) {
    var mod = qutient % radix;
    arr.push(chars[mod]);
    qutient = (qutient - mod) / radix;
    if (qutient < radix) {
      arr.push(chars[qutient]);
      qutient = 0;
    }
  }
  return arr.join('');
}

//生成认证证明证书
function createCert(data) {
  return new Promise((resolve, reject) => {
    try {
      const doc = new PDFDocument();

      var outPath = Path.join(
        __dirname,
        `../cache/${data.phone}-${data.type}.pdf`
      );
      var output = fs.createWriteStream(outPath);
      doc.pipe(output);

      var titleX = 60;
      var contentX = 180;
      var y = 80;
      var lineHeight = 35;
      doc.registerFont(
        'Heavy',
        Path.join(__dirname, '../static/fonts/Alibaba-PuHuiTi-Heavy.ttf')
      );
      doc.registerFont(
        'Medium',
        Path.join(__dirname, '../static/fonts/Alibaba-PuHuiTi-Medium.ttf')
      );

      doc.image(Path.join(__dirname, '../static/cert.jpg'), 0, 0, {
        width: 1080 / 1.8,
        height: 791 / 1.8
      });
      y += lineHeight * 1.5;

      //区块高度
      doc.font('Medium').fillColor('#464647').fontSize(20);
      doc.text('区块高度', titleX, y);
      doc.fillColor('#717172');
      doc.text(data.ledger, contentX, y);

      y += lineHeight * 1.3;

      //交易hash
      doc.fillColor('#464647');
      doc.text('交易哈希', titleX, y);
      doc.fillColor('#717172');
      doc.text(data.hash, contentX, y);
      y += lineHeight * 2.5;

      //认证时间
      doc.fillColor('#464647');
      doc.text('认证时间', titleX, y);
      doc.fillColor('#717172');
      var time = moment(data.time).format('yyyy/MM/DD HH:mm:ss');
      doc.text(time, contentX, y);
      y += lineHeight * 1.2;

      if (data.type == config.AUTH_TYPE.PERSONAL) {
        //姓名
        doc.fillColor('#464647');
        doc.text('真实姓名', titleX, y);
        doc.fillColor('#717172');
        doc.text(data.name, contentX, y);
        y += lineHeight * 1.2;

        //身份证号
        doc.fillColor('#464647');
        doc.text('身份证号', titleX, y);
        doc.fillColor('#717172');
        doc.text(data.idcard, contentX, y);
      } else {
        //公司
        doc.fillColor('#464647');
        doc.text('企业名称', titleX, y);
        doc.fillColor('#717172');
        doc.text(data.name, contentX, y);
      }
      doc.end();
      output.on('close', function () {
        resolve(outPath);
      });
    } catch (error) {
      reject(error);
    }
  });
}

//获取chainsql交易总数
function getTxCount(con) {
  return new Promise((resolve, reject) => {
    con._ws.send(
      JSON.stringify({
        id: 3,
        command: 'tx_count'
      })
    );
    con._ws.on('message', function (data) {
      var info = JSON.parse(data);
      if (info.id == 3) {
        resolve(info.result.all);
      }
    });
  });
}
/**
 * 验证交易
 * @param {String} hash 交易hash
 * @param {String} walletAddress 发起交易地址
 * @param {String} code 交易码
 * @param {String} amount 交易额
 * @param {String} amount 支付类型
 * @return {Object} 1成功2失败3查询链失败,需联系客服
 */
async function verifyTx(hash, walletAddress, code, amount, type) {
  var res;
  var result = {};
  try {
    await chainsql.init();
    res = await chainsql.c.getTransaction(hash);
  } catch (error) {
    console.log(error);
    result.code = 3;
  }
  //校验交易是否合法
  var memos = JSON.parse(res.specification.memos[0].data);
  if (
    res.address == walletAddress &&
    res.outcome.result == 'tesSUCCESS' &&
    res.outcome.deliveredAmount.currency == config.chainsql.pointCoin &&
    res.outcome.deliveredAmount.value ==
      Math.abs(parseInt(amount)).toString() &&
    res.specification.destination.address == config.chainsql.chainAdmin &&
    memos.type == type &&
    memos.code == code
  ) {
    result.code = 1;
    result.res = res;
  } else {
    result.code = 2;
  }
  return result;
}

//获取给定时间之前最近的一个区块信息
async function getLatestLedger(time) {
  time = moment(time).utc().format('YYYY-MM-DDTHH:mm:ss');
  var url = `${config.chainsql.his}/ledgers/${time}`;
  var res = await got.get(url, {
    responseType: 'json'
  });
  return res.body.ledger;
}

function sleep(s) {
  return new Promise(function (reslove, reject) {
    setTimeout(function () {
      reslove();
    }, s * 1000);
  });
}

//生成6位随机字符串
function generateRandomCode(len) {
  if (!len) {
    len = 6;
  }
  let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
  let maxPos = chars.length;
  var code = '';
  for (let i = 0; i < len; i++) {
    code += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return code;
}

exports = module.exports = {
  schema,
  sendSMS,
  getClientIp,
  string10to52,
  createCert,
  uploadFile,
  downloadFile,
  sha256,
  getTxCount,
  verifyTx,
  getLatestLedger,
  sleep,
  generateRandomCode
};
